package nebula

import (
	"io"
	"sync"

	"github.com/tinylib/msgp/msgp"
)

type ExitStatus int

const (
	NoneExit ExitStatus = iota
	ClientExit
	ServerExit
)

type MT uint8

const (
	P_OPEN MT = iota
	P_REOPEN
	P_CLOSE
	P_PING
	P_PONG
	P_APPLICATION
	P_NAMESPACE
	//P_PROTOCOL
)

type NS byte

const (
	NSP_DEFAULT NS = iota
)

type NSP []byte

type NSE byte

type NsDataType byte

const (
	N_CONNECT NsDataType = iota
	N_DISCONNECT
	N_EVENT
	N_ACK
	N_ERROR
)

//go:generate msgp
//msgp:tuple NsData AppPacket
type NsData struct {
	Type NsDataType  `msg:"type"`
	Id   int         `msg:"id"`
	NSP  NSP         `msg:"nsp"`
	Data interface{} `msg:"data"`
}

type NsDataArray []*NsData

func NewNsDataArray() *NsDataArray {
	return &NsDataArray{}
}

//封包
func (p *NsDataArray) Encode(writer io.Writer) error {
	return msgp.Encode(writer, p)
}

//解包
func (p *NsDataArray) Decode(reader io.Reader) error {
	return msgp.Decode(reader, p)
}

type App interface {
	GetId() string
	GetVersion() string
	GetToken() string
}

type AppPacket struct {
	Id      string `msg:"id"`
	Version string `msg:"version"`
	Token   string `msg:"token"`

	b []byte
}

func NewAppData() *AppPacket {
	return &AppPacket{b: []byte{}}
}

//封包
func (p *AppPacket) Encode(writer io.Writer) error {
	return msgp.Encode(writer, p)
}

//解包
func (p *AppPacket) Decode(reader io.Reader) error {
	return msgp.Decode(reader, p)
}

func (p *AppPacket) GetId() string {
	return p.Id
}

func (p *AppPacket) GetVersion() string {
	return p.Version
}

func (p *AppPacket) GetToken() string {
	return p.Token
}

var (
	appPool    = sync.Pool{}
	nsDataPool = sync.Pool{}
)

func init() {
	appPool.New = func() interface{} {
		return NewAppData()
	}
	nsDataPool.New = func() interface{} {
		return NewNsDataArray()
	}
}

func GetApp() *AppPacket {
	return appPool.Get().(*AppPacket)
}

func GetNsData() *NsDataArray {
	return nsDataPool.Get().(*NsDataArray)
}

func (p *AppPacket) Release() {
	if p != nil {
		appPool.Put(p)
	}
}

func (p *NsDataArray) Release() {
	if p != nil {
		nsDataPool.Put(p)
	}
}
